/**
 * 
 */
package unifor.filetransfer.util;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.security.NoSuchAlgorithmException;

import unifor.filetransfer.Principal;

import jonelo.jacksum.JacksumAPI;
import jonelo.jacksum.algorithm.AbstractChecksum;

/**
 * @author landim
 * 
 */
public class TransmissaoUtil {

    /**
     * Gerar o cabecalho do PDU de envio
     * @param to
     * @return
     */
    public static byte[] gerarCabecalhoPduEnvio(ConfiguracaoTO to) {
        byte[] result = null;

        String fileName = to.getNomeArquivo().replaceAll(".*\\\\", "");
        fileName = fileName.replaceAll(".*\\/", "");

        Principal.logTrans("preparando cabecalho do pdu");
        byte[] fileBytes = fileName.getBytes();

        //Se o tamanho do nome do arquivo for maior que 240, colocar 240
        int tamanhoNomeArquivo = (fileBytes.length >= 240 ? 240 : fileBytes.length);
        result = new byte[8 + tamanhoNomeArquivo];

        //===========Tipo de PDU - Envio==============
        result[0] = CabecalhoPdu.ENVIO;        
        
        //===========Tamanho do cabecalho=============
        result[3] = (byte) result.length;
        
        
        //==============nome do arquivo===============
        System.arraycopy(fileBytes, 0, result, 8, tamanhoNomeArquivo);

        AbstractChecksum crc = null;
		try {
			crc = JacksumAPI.getChecksumInstance("crc16");
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		Principal.logTrans("Determinando o tamanho do arquivo");
		
        //=============Tamanho do arquivo=============
        int tamanhoArquivo = 0;
        
        InputStream in = null;
        int restante = to.getTamanhoSegmento() - result.length;
		try {
			in = new BufferedInputStream(new FileInputStream(to.getNomeArquivo()));
	        byte[] segmento = lerBytesDoArquivo(in, restante);
	        while ( segmento != null) {
	            crc.update(segmento);

	            tamanhoArquivo += segmento.length;
	            segmento = lerBytesDoArquivo(in, to.getTamanhoSegmento());
	        }		

	        in.close();
	    } catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        

        to.setTamanhoArquivo(tamanhoArquivo);
        result[4] = ProtocoloUtil.toByteArray(tamanhoArquivo, 4)[0];
        result[5] = ProtocoloUtil.toByteArray(tamanhoArquivo, 4)[1];
        result[6] = ProtocoloUtil.toByteArray(tamanhoArquivo, 4)[2];
        result[7] = ProtocoloUtil.toByteArray(tamanhoArquivo, 4)[3];
        
        crc.update(result);
        
        byte[] crcByte = crc.getByteArray();
        //===============CRC==========================
        result[1] = crcByte[0];
        result[2] = crcByte[1];
        
//        index = 0;
//        segmento = lerBytesDoArquivo(to.getNomeArquivo(), index, to.getTamanhoSegmento());
//        while ( segmento != null) {
//            index += segmento.length;
//            segmento = lerBytesDoArquivo(to.getNomeArquivo(), index, to.getTamanhoSegmento());
//            
//            //Calcular CRC do cabecalho + do arquivo
//        }
        //Setar CRC
//        result[1] = 0;
//        result[2] = 0;
        
        Principal.logTrans("_____________________________________");
        Principal.logTrans("| 1 | " + result[1] + " | " + result[2]+ " | " + result[3]+ " | " + result[4]+ " | " + result[5]+ " | " + result[6]+ " | " + result[7]+ " |");
        Principal.logTrans("_____________________________________");
        
        return result;
    }
    
    /**
     * Gerar o cabecalho do PDU de envio
     * @param correto boolean, se recebeu correto, true, senao false!
     * @return
     */
    public static byte[] gerarPduResposta(boolean correto) {
        byte[] result = null;

        result = new byte[2];

        //Tipo de PDU - Resposta
        result[0] = 2;
        //Se for true, 1
        result[1] = (byte) (correto ? 1 : 2);

        return result;
    }
    /**
     * Ler bytes de um arquivo.
     * @param fileName Nome do arquivo
     * @param inicio qual byte vai inicar a leitura
     * @param tamanho quantos bytes vao ser lidos
     * @return
     */
    public static byte[] lerBytesDoArquivo(InputStream in, int tamanho) {

        byte[] result  = null;

       try{

          // tamanho que quer ler
          int bufLen = tamanho;
          
          byte[] buf = new byte[bufLen];
          byte[] tmp = null;
          int len    = 0;
          
          
          if ((len = in.read(buf, 0, bufLen)) != -1){
        	  
        	  if (len < bufLen)  {
                  // extend array
                  tmp = new byte[len];

                 // copy data
                 System.arraycopy(buf,0,tmp,0,len);
                 result = tmp;
                 tmp = null;
        	  } else {
        		  result = buf;
        	  }
        	  
          } else {
              result = null;
          }

       } catch (Exception e) {
           result = null;
       }
       return result;
    }
    
    
    
}
